package ar.edu.uba.fi.jmit.monitorengine.integration;

import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import ar.edu.uba.fi.jmit.monitorengine.MonitorEngineTestCase;
import ar.edu.uba.fi.jmit.monitorengine.core.ConfigurationManager;
import ar.edu.uba.fi.jmit.monitorengine.core.RangeObserver;
import ar.edu.uba.fi.jmit.monitorengine.core.rangeobserver.MethodInvocationCounterRangeObserver;
import ar.edu.uba.fi.jmit.monitorengine.parser.ParsersManager;
import ar.edu.uba.fi.jmit.monitorengine.parser.XMLMonitorEngineParser;

public class XMLMonitorEngineParserTestCase extends MonitorEngineTestCase {
	
	private static String CONFIGURATION_FILES_PATH = "src/test/resources/testParser";
	protected static Logger logger = Logger.getLogger(XMLMonitorEngineParserTestCase.class);

	public void testWithManyMonitors() {
		try {
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/ManyMonitors.jmit.xml");
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("testInvocationCounter2");
			assertNotNull(configuration);
			assertEquals("getX", configuration.get("methodConfiguration.method.name"));
			assertEquals("java.lang.Integer", configuration.get("methodConfiguration.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.itegration.testUtils.PointTestInvocationCounter", configuration.get("methodConfiguration.method.class"));
			assertEquals("data", configuration.get("methodConfiguration.method.param.name"));
			assertEquals("int", configuration.get("methodConfiguration.method.param.type"));
			
			configuration = ConfigurationManager.getInstance().getConfiguration("PointTestObjectCounter2");
			assertNotNull(configuration);
			assertEquals("setY", configuration.get("methodToIntercept.method.name"));
			assertEquals("void", configuration.get("methodToIntercept.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest12", configuration.get("methodToIntercept.method.class"));
			
			configuration = ConfigurationManager.getInstance().getConfiguration("valorYPointTestFieldValue2");
			assertNotNull(configuration);
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.coreTest.PointTestFieldValue", configuration.get("classConfiguration.class.name"));
			assertEquals("x", configuration.get("classConfiguration.class.id"));
			assertEquals("y", configuration.get("fieldConfiguration.field.name"));
			assertEquals("java.lang.Integer", configuration.get("fieldConfiguration.field.type"));
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testEnviromentDevelopmentFile() {
		try {
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/EnviromentDevelopment.jmit.xml");
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("instanciasPointTestObjectCounter");
			assertNotNull(configuration);
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.coreTest.PointTestObjectCounter", configuration.get("classConfiguration.class.name"));
			assertEquals("x", configuration.get("classConfiguration.class.id"));
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testFieldValueFile() {
		try {
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/FieldValue.jmit.xml");
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("valorYPointTestFieldValue");
			assertNotNull(configuration);
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.coreTest.PointTestFieldValue", configuration.get("classConfiguration.class.name"));
			assertEquals("x", configuration.get("classConfiguration.class.id"));
			assertEquals("y", configuration.get("fieldConfiguration.field.name"));
			assertEquals("java.lang.Integer", configuration.get("fieldConfiguration.field.type"));
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testPluginMonitorFile() {
		try {
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/PluginMonitor.jmit.xml");
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("PointTestObjectCounter");
			assertNotNull(configuration);
			assertEquals("setY", configuration.get("methodToIntercept.method.name"));
			assertEquals("void", configuration.get("methodToIntercept.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest12", configuration.get("methodToIntercept.method.class"));
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testInvocationCounterFile() {
		try {
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/InvocationCounter.jmit.xml");
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("testInvocationCounter");
			assertNotNull(configuration);
			assertEquals("getX", configuration.get("methodConfiguration.method.name"));
			assertEquals("java.lang.Integer", configuration.get("methodConfiguration.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.itegration.testUtils.PointTestInvocationCounter", configuration.get("methodConfiguration.method.class"));
			assertEquals("data", configuration.get("methodConfiguration.method.param.name"));
			assertEquals("int", configuration.get("methodConfiguration.method.param.type"));
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testWithManyMonitorConfigurationFiles() {
		try {
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/FieldValue2.jmit.xml");
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("valorYPointTestFieldValue5");
			assertNotNull(configuration);
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.coreTest.PointTestFieldValue", configuration.get("classConfiguration.class.name"));
			assertEquals("x", configuration.get("classConfiguration.class.id"));
			assertEquals("y", configuration.get("fieldConfiguration.field.name"));
			assertEquals("java.lang.Integer", configuration.get("fieldConfiguration.field.type"));
		} catch (Exception e) {
			fail(e);
		}
		try {			
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/InvocationCounter2.jmit.xml");
			
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("valorYPointTestFieldValue5");
			assertNotNull(configuration);
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.coreTest.PointTestFieldValue", configuration.get("classConfiguration.class.name"));
			assertEquals("x", configuration.get("classConfiguration.class.id"));
			assertEquals("y", configuration.get("fieldConfiguration.field.name"));
			assertEquals("java.lang.Integer", configuration.get("fieldConfiguration.field.type"));
			
			configuration = ConfigurationManager.getInstance().getConfiguration("testInvocationCounter5");
			assertNotNull(configuration);
			assertEquals("getX", configuration.get("methodConfiguration.method.name"));
			assertEquals("java.lang.Integer", configuration.get("methodConfiguration.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.itegration.testUtils.PointTestInvocationCounter", configuration.get("methodConfiguration.method.class"));
			assertEquals("data", configuration.get("methodConfiguration.method.param.name"));
			assertEquals("int", configuration.get("methodConfiguration.method.param.type"));
		} catch (Exception e) {
			fail(e);
		}
		try {
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/PluginMonitor2.jmit.xml");
			
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("valorYPointTestFieldValue5");
			assertNotNull(configuration);
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.coreTest.PointTestFieldValue", configuration.get("classConfiguration.class.name"));
			assertEquals("x", configuration.get("classConfiguration.class.id"));
			assertEquals("y", configuration.get("fieldConfiguration.field.name"));
			assertEquals("java.lang.Integer", configuration.get("fieldConfiguration.field.type"));
			
			configuration = ConfigurationManager.getInstance().getConfiguration("testInvocationCounter5");
			assertNotNull(configuration);
			assertEquals("getX", configuration.get("methodConfiguration.method.name"));
			assertEquals("java.lang.Integer", configuration.get("methodConfiguration.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.itegration.testUtils.PointTestInvocationCounter", configuration.get("methodConfiguration.method.class"));
			assertEquals("data", configuration.get("methodConfiguration.method.param.name"));
			assertEquals("int", configuration.get("methodConfiguration.method.param.type"));
			
			configuration = ConfigurationManager.getInstance().getConfiguration("PointTestObjectCounter5");
			assertNotNull(configuration);
			assertEquals("setY", configuration.get("methodToIntercept.method.name"));
			assertEquals("void", configuration.get("methodToIntercept.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest12", configuration.get("methodToIntercept.method.class"));
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testParseCompleteDirectory() {		
		try {
			ParsersManager.loadConfigurations("src/test/resources/testParser2");
			
			Map<String, String> configuration = ConfigurationManager.getInstance().getConfiguration("testInvocationCounter3");
			assertNotNull(configuration);
			assertEquals("getX", configuration.get("methodConfiguration.method.name"));
			assertEquals("java.lang.Integer", configuration.get("methodConfiguration.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.itegration.testUtils.PointTestInvocationCounter", configuration.get("methodConfiguration.method.class"));
			assertEquals("data", configuration.get("methodConfiguration.method.param.name"));
			assertEquals("int", configuration.get("methodConfiguration.method.param.type"));
			
			configuration = ConfigurationManager.getInstance().getConfiguration("PointTestObjectCounter4");
			assertNotNull(configuration);
			assertEquals("setY", configuration.get("methodToIntercept.method.name"));
			assertEquals("void", configuration.get("methodToIntercept.method.return"));
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.PointTest12", configuration.get("methodToIntercept.method.class"));
			
			configuration = ConfigurationManager.getInstance().getConfiguration("valorYPointTestFieldValue3");
			assertNotNull(configuration);
			assertEquals("ar.edu.uba.fi.jmit.aspecter.testUtils.coreTest.PointTestFieldValue", configuration.get("classConfiguration.class.name"));
			assertEquals("x", configuration.get("classConfiguration.class.id"));
			assertEquals("y", configuration.get("fieldConfiguration.field.name"));
			assertEquals("java.lang.Integer", configuration.get("fieldConfiguration.field.type"));
		} catch (Exception e) {
			fail(e);
		}
	}
	
	public void testGetRangeObservers() {
		try {
			XMLMonitorEngineParser.parse(CONFIGURATION_FILES_PATH + "/Ranges.jmit.xml");
			
			List<RangeObserver> ranges = ConfigurationManager.getInstance().getRangeObservers("TestRanges");
			assertNotNull(ranges);
			assertEquals(2, ranges.size());
			RangeObserver range = ranges.get(0);
			assertTrue(range instanceof MethodInvocationCounterRangeObserver);
			MethodInvocationCounterRangeObserver rangeMethodInvocationCounter = (MethodInvocationCounterRangeObserver)range;
			assertEquals("Prueba", rangeMethodInvocationCounter.getName());
			assertEquals("Esto es una prueba del parseo de rangos", rangeMethodInvocationCounter.getSeverity());
			assertEquals(new Long(10), rangeMethodInvocationCounter.getMinValue());
			assertEquals(new Long(20), rangeMethodInvocationCounter.getMaxValue());
			assertEquals(new Long(1000), rangeMethodInvocationCounter.getTimeOutOfRangeAllowed());
			assertEquals(false, rangeMethodInvocationCounter.isAlert());
			
			range = ranges.get(1);
			assertTrue(range instanceof MethodInvocationCounterRangeObserver);
			rangeMethodInvocationCounter = (MethodInvocationCounterRangeObserver)range;
			assertEquals("Prueba2", rangeMethodInvocationCounter.getName());
			assertEquals(new Long(5), rangeMethodInvocationCounter.getMinValue());
			assertEquals(true, rangeMethodInvocationCounter.isAlert());
			
		} catch (Exception e) {
			fail(e);
		}
	}
}
